package com.hou.elasticsearch.controller;

import com.alibaba.fastjson.JSONObject;
import com.hou.elasticsearch.bean.Book;
import com.hou.elasticsearch.bean.Person;
import com.hou.elasticsearch.utils.ElasticSearchUtils;
import com.hou.elasticsearch.utils.PageBean;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequestMapping("/test")
public class EsSearchController {

    @GetMapping("/hello")
    public String helloTest() {
        return "Holle World";
    }


    /**
     * 测试索引
     */
    private String indexName = "entity";
    /**
     * 类型
     */
    private String esType = "book";

    /**
     * http://127.0.0.1:8080/test/createIndex
     * 创建索引
     *
     * @return
     */
    @GetMapping("/createIndex")
    public String createIndex() {
        if (!ElasticSearchUtils.isIndexExist(indexName)) {
            ElasticSearchUtils.createIndex(indexName);
        } else {
            return "索引已经存在";
        }
        return "索引创建成功";
    }

    /**
     * 创建索引以及类型，并给索引某些字段指定iK分词，以后向该索引中查询时，就会用ik分词。
     *
     * @param: [request, response]
     * @return: java.lang.String
     */
    @GetMapping("/createIndexTypeMapping")
    public String createIndexTypeMapping() {
        if (!ElasticSearchUtils.isIndexExist(indexName)) {
            ElasticSearchUtils.createIndex(indexName, esType);
        } else {
            return "索引已经存在";
        }
        return "索引创建成功";
    }

    @GetMapping("/deleteIndex")
    public String deleteIndex(String indexName) {
        boolean b = ElasticSearchUtils.deleteIndex(indexName);
        if (!b) {
            return "失败";
        }
        return "索引删除成功";
    }

    /**
     * ik分词测试
     */
    @GetMapping("getik")
    public String ikMapping() {
        String ik = ElasticSearchUtils.ik();
        return ik;
    }


    /**
     * 插入记录
     *
     * @return
     */
    @GetMapping("/insertJson")
    public String insertJson() {
        JSONObject jsonOject = new JSONObject();
        jsonOject.put("id", DateFormatUtils.format(new Date(), "yyyyMMddhhmmss"));
        jsonOject.put("name", "我和漂亮空姐同居的日子");
        jsonOject.put("message", "这是一本言情小说");
        jsonOject.put("price", 99.9);
        jsonOject.put("createDate", new Date());
        //或者直接对象转json
        //JSONObject jsonObject = (JSONObject) JSONObject.toJSON(person);
        String id = ElasticSearchUtils.addData(jsonOject, indexName, esType, jsonOject.getString("id"));
        return id;
    }


    /**
     * 删除记录
     *
     * @return
     */
    @GetMapping("/delete")
    public String delete(String id) {
        if (StringUtils.isNotBlank(id)) {
            ElasticSearchUtils.deleteDataById(indexName, esType, id);
            return "删除id=" + id;
        } else {
            return "id为空";
        }
    }

    /**
     * 更新数据
     *
     * @return
     */
    @GetMapping("/update/{id}")
    public String update(@PathVariable("id") String id) {
        if (StringUtils.isNotBlank(id)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", id);
            jsonObject.put("age", 31);
            jsonObject.put("name", "修改");
            jsonObject.put("name", "修改");
            jsonObject.put("date", new Date());
            ElasticSearchUtils.updateDataById(jsonObject, indexName, esType, id);
            return "id=" + id;
        } else {
            return "id为空";
        }
    }

    /**
     * 获取数据
     */
    @GetMapping("/getData/{id}")
    public String getData(@PathVariable("id") String id) {
        if (StringUtils.isNotBlank(id)) {
            Map<String, Object> map = ElasticSearchUtils.searchDataById(indexName, esType, id, null);
            return JSONObject.toJSONString(map);
        } else {
            return "id为空";
        }
    }

    /**
     * 查询数据
     * 模糊查询
     *
     * @return
     */
    @GetMapping("/queryMatchData")
    public String queryMatchData() {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolean matchPhrase = true;
        if (matchPhrase == Boolean.TRUE) {
            //matchPhraseQuery: 希望寻找邻近的单词时,可以帮助查找到,比如,查询同居时同住也可能查到
            boolQuery.must(QueryBuilders.matchPhraseQuery("name", "空姐"));
        } else {
            boolQuery.must(QueryBuilders.matchQuery("name", "同居"));
        }
        List<Map<String, Object>> list = ElasticSearchUtils.searchListData(indexName, esType, boolQuery,
                10, null, null, null);
        return JSONObject.toJSONString(list);
    }

    /**
     * 通配符查询数据
     * 通配符查询 ?用来匹配1个任意字符，*用来匹配零个或者多个字符
     *
     * @return
     */
    @GetMapping("/queryWildcardData")
    public String queryWildcardData() {
        QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("name.keyword", "书名*2");
        List<Map<String, Object>> list = ElasticSearchUtils.searchListData(indexName, esType, queryBuilder,
                10, null, null, null);
        return JSONObject.toJSONString(list);
    }

    /**
     * 正则查询
     *
     * @return
     */
    @GetMapping("/queryRegexpData")
    public String queryRegexpData() {
        QueryBuilder queryBuilder = QueryBuilders.regexpQuery("name.keyword", "书名[0-9]{1,7}");
        List<Map<String, Object>> list = ElasticSearchUtils.searchListData(indexName, esType, queryBuilder,
                10, null, null, null);
        return JSONObject.toJSONString(list);
    }

    /**
     * 查询数字范围数据
     *
     * @return
     */
    @GetMapping("/queryIntRangeData")
    public String queryIntRangeData() {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.rangeQuery("price").from(21.0).to(25.0)
                .includeLower(true)  // true  包含下界， false 不包含下界
                .includeUpper(false)); // true  包含下界， false 不包含下界
        List<Map<String, Object>> list = ElasticSearchUtils.searchListData(indexName, esType, boolQuery,
                10, null, null, null);
        return JSONObject.toJSONString(list);
    }

    /**
     * 查询日期范围数据
     *
     * @return
     */
    @GetMapping("/queryDateRangeData")
    public String queryDateRangeData() {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.rangeQuery("creatDate").from("2018-10-17T02:03:08.829Z").to("2018-10-17T02:03:09.727Z")
                .includeLower(true).includeUpper(true));
        List<Map<String, Object>> list = ElasticSearchUtils.searchListData(indexName, esType, boolQuery,
                10, null, null, null);
        return JSONObject.toJSONString(list);
    }

    /**
     * 查询分页  高亮   排序
     *
     * @param startPage 第几条记录开始
     *                  从0开始
     * @param pageSize  每页大小
     * @return
     */
    @GetMapping("/queryPage")
    public String queryPage(String startPage, String pageSize, String context) {
        if (StringUtils.isNotBlank(startPage) && StringUtils.isNotBlank(pageSize)) {
            long start = System.currentTimeMillis();
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            boolQuery.must(QueryBuilders.rangeQuery("creatDate").from("2018-10-17T02:03:08.829Z").to("2018-10-17T02:03:09.727Z").includeLower(true).includeUpper(true))
                    .filter(QueryBuilders.matchQuery("name", context));
//            boolQuery.filter(QueryBuilders.matchQuery("name",context));
            PageBean list = ElasticSearchUtils.searchDataPage(indexName, esType, Integer.parseInt(startPage), Integer.parseInt(pageSize), boolQuery, null, "price", "name");
            long end = System.currentTimeMillis();
            System.out.println((end - start) / 1000 + "s");
            System.out.println((end - start) + "ms");
            return JSONObject.toJSONString(list);
        } else {
            return "startPage或者pageSize缺失";
        }
    }

    /**
     * 深度排序 分页  从当前页为1001开始
     *
     * @param: [startPage, pageSize]
     * @return: com.aqh.utils.EsPage
     */
    @GetMapping("/deepPageing")
    public PageBean deepPageing(int startPage, int pageSize) {
        if (startPage < (10000 / pageSize)) {
            System.out.println("startPage需要>=" + (10000 / pageSize));
        }
        long start = System.currentTimeMillis();
        PageBean result = ElasticSearchUtils.deepPageing(indexName, esType, startPage, pageSize, "name");
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000 + "s");
        System.out.println((end - start) + "ms");
        return result;
    }

    /**
     * 批量添加
     *
     * @param: []
     * @return: org.elasticsearch.rest.RestStatus
     */
    @GetMapping("addBulk")
    public void addBulk() {
        List<Book> bookList = Stream
                .iterate(1, i -> i + 1)
                .limit(100000L)
                .parallel()
                .map(integer -> new Book(String.valueOf(integer), "书名" + integer, "信息" + integer, Double.valueOf(integer), new Date()))
                .collect(Collectors.toList());
        long start = System.currentTimeMillis();
        ElasticSearchUtils.bulkAddDocument(indexName, esType, bookList);
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000 + "s");
        System.out.println((end - start) + "ms");
    }

    /**
     * 批量添加
     *
     * @param: []
     * @return: void
     */
    @GetMapping("/bulkProcessorAdd")
    public void bulkProcessorAdd() {
        List<Book> bookList = Stream
                .iterate(1, i -> i + 1)
                .limit(1000000L)
                .parallel()
                .map(integer -> new Book(String.valueOf(integer), "书名" + integer, "信息" + integer, Double.valueOf(integer), new Date()))
                .collect(Collectors.toList());
        long start = System.currentTimeMillis();
        ElasticSearchUtils.bulkProcessorAdd(indexName, esType, bookList);
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000 + "s");
        System.out.println((end - start) + "ms");
    }

    /**
     * 批量删除
     *
     * @param: []
     * @return: org.elasticsearch.rest.RestStatus
     */
    @GetMapping("deleteBulk")
    public RestStatus deleteBulk() {
        List<String> idsList = Stream
                .iterate(1, i -> i + 1)
                .limit(100000L)
                .parallel()
                .map(integer -> String.valueOf(integer))
                .collect(Collectors.toList());
        long start = System.currentTimeMillis();
        BulkResponse bulkItemResponses = ElasticSearchUtils.bulkDeleteDocument(indexName, esType, idsList);
        if (bulkItemResponses.hasFailures()) {
            System.out.println(bulkItemResponses.buildFailureMessage());
        }
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000 + "s");
        System.out.println((end - start) + "ms");
        return bulkItemResponses.status();
    }


    /**
     * 获取所有
     *
     * @param: []
     * @return: java.lang.String
     */
    @GetMapping("/getAll")
    public List<String> getAll() {
        return ElasticSearchUtils.searchAll(indexName);
    }
}
